﻿

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

//1.模仿冒泡排序来实现排列任意类型的数据
//2.bit关于数组(一维+二维)的练习
//3.指针运算笔试题(最后一题绝对不一般,一般人做不出来)

void bolle(int arr[], int sz)
{
	//一趟
	for (int i = 0; i < sz - 1; i++)
	{
		//一次交换
		for (int j = 0; j < sz - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int tem = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tem;
			}
		}
	}

}

//打印
void print(int arr[], int n)
{
	int i = 0;
	for (i = 0; i < n; i++)
	{
		printf("%d ", arr[i]);
	}
}

void text1()
{
	int arr[] = { 1,3,5,7,9,2,4,6,8,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);

	bolle(arr, sz);
	print(arr, sz);
}

int cmp(const void* e1, const void* e2)
{
	return *(int*)e1 - *(int*)e2;
}

void Swap(char* e1, char* e2, size_t size)
{
	for (int i = 0; i < size; i++)
	{
		char tem = *e1;
		*e1 = *e2;
		*e2 = tem;
		e1++;
		e2++;
	}
}

void bolle_sqort(void* base, size_t num, size_t size, int (*pa)(const void* e1, const void* e2))
{
	for (int i = 0; i < num - 1; i++)
	{
		for (int j = 0; j < num - 1 - i; j++)
		{
			//判断
			if (pa((char*)base + j * size, (char*)base + (j + 1) * size) > 0)
			{
				//交换
				Swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
			}
		}
	}
}

//模仿冒泡排序来实现排列任意类型的数据
void text2()
{
	int arr[] = { 1,3,5,7,9,2,4,6,8,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);

	bolle_sqort(arr, sz,sizeof(arr[0]),cmp);
	print(arr, sz);
}

void text3()
{
	int arr[] = { 1,2,3,4 };
	printf("%zd\n", sizeof(arr));           //16
	printf("%zd\n", sizeof(arr+0));         //4|8  (首元素地址)
	printf("%zd\n", sizeof(*arr));          //4    (首元素的大小) 
	printf("%zd\n", sizeof(arr+1));         //4|8  (第二个元素地址)
	printf("%zd\n", sizeof(arr[1]));        //4
	printf("%zd\n", sizeof(&arr));          //4|8  (数组的地址)
	printf("%zd\n", sizeof(*&arr));         //16   (&和*抵消)
	printf("%zd\n", sizeof(&arr+1));        //4|8  (是跳过整个数组的后面那个地址，是地址)
	printf("%zd\n", sizeof(&arr[0]));       //4|8
	printf("%zd\n", sizeof(&arr[0]+1));     //4|8 

}

void text4()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%zd\n", sizeof(arr));            //6
	printf("%zd\n", sizeof(arr + 0));        //4|8
	printf("%zd\n", sizeof(*arr));           //1
	printf("%zd\n", sizeof(arr[1]));         //1
	printf("%zd\n", sizeof(&arr));           //4|8
	printf("%zd\n", sizeof(&arr + 1));       //4|8
	printf("%zd\n", sizeof(&arr[0] + 1));    //4|8
}

void text5()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%zd\n", strlen(arr));//随机值
	printf("%zd\n", strlen(arr + 0));//随机值
	printf("%zd\n", strlen(*arr));//err  程序崩了，这里应该传地址而不是值；
	printf("%zd\n", strlen(arr[1]));//err  和上面一样，程序崩了；
	printf("%zd\n", strlen(&arr));//随机值
	printf("%zd\n", strlen(&arr + 1));//随机值
	printf("%zd\n", strlen(&arr[0] + 1));//随机值
}

void text6()
{
	char arr[] = "abcdef";
	printf("%zd\n", sizeof(arr));//7
	printf("%zd\n", sizeof(arr + 0));//4|8
	printf("%zd\n", sizeof(*arr));//1
	printf("%zd\n", sizeof(arr[1]));//1
	printf("%zd\n", sizeof(&arr));//4|8
	printf("%zd\n", sizeof(&arr + 1));//4|8
	printf("%zd\n", sizeof(&arr[0] + 1));//4|8
}

void text7()
{
	char arr[] = "abcdef";
	printf("%d\n", strlen(arr));//6
	printf("%d\n", strlen(arr + 0));//6
	//printf("%d\n", strlen(*arr));//err
	//printf("%d\n", strlen(arr[1]));//err
	printf("%d\n", strlen(&arr));//6
	printf("%d\n", strlen(&arr + 1));//随机值
	printf("%d\n", strlen(&arr[0] + 1));//5
}

void text8()
{
	char* p = "abcdef";
	printf("%zd\n", sizeof(p));//4|8  计算p这个指针变量的大小
	printf("%zd\n", sizeof(p + 1));//4|8  ‘b’这个地址
	printf("%zd\n", sizeof(*p));//1
	printf("%zd\n", sizeof(p[0]));//1
	printf("%zd\n", sizeof(&p));//4|8    指针变量p的地址
	printf("%zd\n", sizeof(&p + 1));//4|8  是指向p指针变量后面的空间，也是地址
	printf("%zd\n", sizeof(&p[0] + 1));//4|8  ‘b’的地址
}
void text9()
{
	char* p = "abcdef";
	printf("%d\n", strlen(p));//6
	printf("%d\n", strlen(p + 1));//5
	//printf("%d\n", strlen(*p));//err
	//printf("%d\n", strlen(p[0]));//err
	printf("%d\n", strlen(&p));//随机值
	printf("%d\n", strlen(&p + 1));//随机值
	printf("%d\n", strlen(&p[0] + 1));//5
}

void text10()
{
	int a[3][4] = { 0 };
	printf("%zd\n", sizeof(a));//48  整个二维数组的大小：3*4*4=48字节
	printf("%zd\n", sizeof(a[0][0]));//4  计算第一个元素的大小
	printf("%zd\n", sizeof(a[0]));//16  是第一行一维数组的数组名，sizeof(数组名)计算整个一维数组的大小
	printf("%zd\n", sizeof(a[0] + 1));//4|8  是第一行第二个元素的地址
	printf("%zd\n", sizeof(*(a[0] + 1)));//4  是第一行第二个元素的大小
	printf("%zd\n", sizeof(a + 1));//4|8   这里的a是第一行的地址，a+1是第二行的地址
	printf("%zd\n", sizeof(*(a + 1)));//16  第二行的数组名
	printf("%zd\n", sizeof(&a[0] + 1));//4|8  第二行的地址
	printf("%zd\n", sizeof(*(&a[0] + 1)));//16   计算第二行的大小
	printf("%zd\n", sizeof(*a));//16   当一个数组名没有单独放在sizeof中，就代表数组首元素地址，
	//而*a就代表第一行
	printf("%zd\n", sizeof(a[3]));//16     
	//因为sizeof中的表达式不会进行计算，
	//计算第四行的大小，
}

//int main()
//{
//	//text1();
//	//text2();
//	//text3();
//	//text4();
//	//text5();
//	//text6();
//	//text7();
//	//text8();
//	//text9();
//	text10();
//	return 0;
//}


//指针运算笔试题
//#include <stdio.h>
//int main()
//{
//	int a[5] = { 1, 2, 3, 4, 5 };
//	int* ptr = (int*)(&a + 1);
//	printf("%d,%d", *(a + 1), *(ptr - 1));
//	return 0;
//}
//程序的结果是什么？
//分析：将a数组后面的地址强制转化为int*类型放入ptr指正变量中；
//答案：2,5

//在X86环境下
//假设结构体的⼤⼩是20个字节
//程序输出的结果是啥？
struct Test
{
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p = (struct Test*)0x100000;
//考的知识点是指针+1
//int main()
//{
//	printf("%p\n", p + 0x1);//0x100014  这里是结构体指针+1   跳过一个结构体
//	printf("%p\n", (unsigned long)p + 0x1);//0x100001  这里是整形+1 
//	printf("%p\n", (unsigned int*)p + 0x1);//0x100004  这里是指针+1
//	return 0;
//}

#include <stdio.h>
//int main()
//{
//	int a[3][2] = { (0, 1), (2, 3), (4, 5) };
//	int* p;
//	p = a[0];
//	printf("%d", p[0]);//1
//	return 0;
//}

//假设环境是x86环境，程序输出的结果是啥？
#include <stdio.h>
//int main()
//{
//	int a[5][5];
//	int(*p)[4];//是一个指针数组，指针+1则跳过4个字节
//	p = a;
//	printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);//FFFFFFFC，-4
//	return 0;
//}
//地址-地址=两个地址之间元素的个数
//而且随着数组访问下标的增大，地址也越高
//%p打印的是地址：将(-4)的补码当成地址打印出来


//#include <stdio.h>
//int main()
//{
//	int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//	int* ptr1 = (int*)(&aa + 1);
//	int* ptr2 = (int*)(*(aa + 1)); //相当于aa[1]，第二行首元素地址
//	printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));//10,5
//	return 0;
//}

//int main()
//{
//	char* a[] = { "work","at","alibaba" };
//	char** pa = a;
//	pa++;
//	printf("%s\n", *pa);//at
//	return 0;
//}


#include <stdio.h>
int main()
{
	char* c[] = { "ENTER","NEW","POINT","FIRST" };
	char** cp[] = { c + 3,c + 2,c + 1,c };
	char*** cpp = cp;
	printf("%s\n", **++cpp);//POINT
	printf("%s\n", *-- * ++cpp + 3);//ER
	printf("%s\n", *cpp[-2] + 3);//ST
	printf("%s\n", cpp[-1][-1] + 1);//EW
	return 0;
}